<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生成九宫格图片</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
    <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"> -->
    <style>
        * {
            box-sizing: border-box;
            padding: 0;
            margin: 0;
            -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        }

        #my-canvas {
            width: 1000px;
            height: 1000px;
            border: 1px solid black;
            position: absolute;
            right: 1000%;
        }

        .imgs-list {
            display: flex;
            flex-wrap: wrap;
            width: 308px;
            height: 308px;
            margin-top: 40px;
            position: relative;
            line-height: 0;
            cursor: pointer;
            --store-width: 4px;
        }

        .imgs-list-bg {
            position: absolute;
            z-index: -1;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            opacity: 0.8;
            filter: blur(16px);
        }

        .imgs-list.loading {
            background-color: #f7f7f7;
            border-radius: 8px;

        }

        .imgs-list.loading::before {
            content: "☞点我选择图片☜";
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            max-width: 100%;
            text-align: center;
            color: #666;
            font-size: 14px;
            white-space: pre-line;
        }

        .imgs-list-item {
            width: 100px;
            height: 100px;
            line-height: 1;
            font-size: 0;
            vertical-align: top;
            margin-left: var(--store-width);
            border-radius: 3px;

        }

        .imgs-list-item:nth-of-type(n+4) {
            margin-top: var(--store-width);
        }

        .imgs-list-item:nth-of-type(3n+1) {
            margin-left: 0px;
        }


        #upload {
            display: none;
        }

        .choose-image {
            background-color: #07C160;
            color: #fff;
            font-size: 14px;
            margin-top: 20px;
            line-height: 40px;
            border-radius: 20px;
            height: 20rpx;
            align-self: center;
            text-align: center;
            width: 120px;
            display: none;
            cursor: pointer;
            user-select: none;
            transition: all 0.2s;
        }

        .choose-image:active {
            opacity: 0.9;
        }

        .choose-image:hover {
            opacity: 0.9;
        }

        #desc-text {
            color: #999;
            margin-top: 10px;
            font-size: 14px;
            display: none;
        }

        .style-1 {
            display: block;
            background-color: #F7F7F7;
            color: #666;
        }
    </style>
</head>

<body>
    <div style="width: 100vw;display: flex;flex-direction: column;align-items: center;user-select: none;">
        <div class="imgs-list loading" onclick="chooseImage()">
            <!-- 背景 -->
            <!-- 背景 -->
        </div>


        <div draggable="false"
            style="position: relative;margin-top: 10px;overflow: hidden;border-radius: 4px;cursor: pointer;user-select: none;"
            id="preview-box">
            <img draggable="false" src="" id="preview"
                style="opacity: 0.8;line-height: 0;vertical-align: top;font-size: 0;">
            <div draggable="false" class="kuangkuang"
                style="width: 80px;height: 80px;position: absolute;left:50%;top: 50%;transform: translate(-50%,-50%);background-color: rgba(0,0,0,0.5);border: 1px dashed #FFF;border-radius: 4px;margin-top:0;margin-left: 0;">
            </div>
        </div>

        <div id="desc-text">点击或者长按单张图片可下载/保存<span style="padding-left: 4px;color:#07C160;"
                onclick="editWidth()">修改间隙</span></div>
        <div style="display: flex;">
            <div class="choose-image style-1" onclick="chooseImage()">选择图片
            </div>
            <div id="save-btn" class="choose-image" style="margin-left: 10px;">保存图片</div>
        </div>
        <!-- 隐藏元素 -->
        <input type="file" id="upload" accept="image/*">
        <canvas id="my-canvas"></canvas>
        <!-- 隐藏元素 -->
    </div>

    <script>
        let cha = 0;
        let leftCha = 0;
        let topCha = 0;
        let aspectRatio = 1;
        const saveBtn = document.getElementById('save-btn');
        let imageParts = [];
        const canvas = document.getElementById('my-canvas');
        let file = null;
        let storeWidht = 4;
        const ctx = canvas.getContext('2d');
        document.getElementById('upload').addEventListener('change', function (event) {
            file = event.target.files[0];
            if (!file) return;
            drawImageHandler();

        });
        function drawImageHandler(refresh = false) {
            console.log('drawImageHandler');
            const reader = new FileReader();
            reader.onload = function (e) {
                const img = new Image();
                img.onload = function () {


                    let minWidth = Math.min(img.width, img.height);
                    let maxWidth = Math.max(img.width, img.height);


                    aspectRatio = img.width / img.height;

                    if (minWidth >= 1500) {
                        minWidth = 1500;
                    }
                    canvas.width = minWidth;
                    canvas.height = minWidth;


                    let drawWidth, drawHeight;
                    drawWidth = minWidth;
                    drawHeight = minWidth / aspectRatio;

                    if (aspectRatio > 1) {
                        drawWidth = drawWidth * aspectRatio;
                        drawHeight = drawHeight * aspectRatio;
                    }

                    if (!refresh) {
                        marginTop = 0;
                        marginLeft = 0;
                        kuangkuang.style.marginTop = 0;
                        kuangkuang.style.marginLeft = 0;
                        cha = Math.abs(drawWidth - drawHeight);
                        leftCha = 0;
                        topCha = 0;

                        preview.src = img.src;
                        preview.style.width = 80 + 'px';
                        preview.style.height = 80 / aspectRatio + 'px';
                        if (aspectRatio > 1) {
                            preview.style.width = 80 * aspectRatio + 'px';
                            preview.style.height = 80 + 'px';
                        }
                    }



                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    ctx.drawImage(img, (canvas.width - drawWidth) / 2 + leftCha, (canvas.height - drawHeight) / 2 + topCha, drawWidth, drawHeight);


                    const imgsList = document.querySelector('.imgs-list');
                    imgsList.innerHTML = '';
                    saveBtn.style.display = 'none';
                    imgsList.classList.add('loading');

                    imageParts = [];
                    //定义分割线宽度

                    for (let row = 0; row < 3; row++) {
                        for (let col = 0; col < 3; col++) {

                            let relaseStoreWIdth = (storeWidht) / (300 + storeWidht * 2) * minWidth;

                            const tempCanvas = document.createElement('canvas');
                            tempCanvas.width = (minWidth - 2 * relaseStoreWIdth) / 3;
                            tempCanvas.height = (minWidth - 2 * relaseStoreWIdth) / 3;
                            const tempCtx = tempCanvas.getContext('2d');

                            tempCtx.drawImage(canvas, col * tempCanvas.width + (relaseStoreWIdth * col), row * tempCanvas.height + (relaseStoreWIdth * row), tempCanvas.width, tempCanvas.height, 0, 0, tempCanvas.width, tempCanvas.height);

                            const partImg = document.createElement('img');
                            partImg.className = 'imgs-list-item';
                            partImg.src = tempCanvas.toDataURL();
                            imageParts.push({ data: tempCanvas.toDataURL(), filename: `${row * 3 + col + 1}-${new Date().getTime()}.png` });
                            imgsList.appendChild(partImg);

                        }
                    }
                    let imgsListBG = document.createElement('div');
                    imgsListBG.className = 'imgs-list-bg';

                    imgsListBG.style.background = `url(${canvas.toDataURL()}) left top / 100% 100% no-repeat`;
                    imgsList.appendChild(imgsListBG);
                    document.querySelector('#desc-text').style.display = 'block';
                    saveBtn.style.display = 'block';
                    imgsList.classList.remove('loading');
                    document.querySelectorAll('.imgs-list-item').forEach((img, index) => {
                        img.addEventListener('click', function (event) {
                            event.stopPropagation()
                            const link = document.createElement('a');
                            link.href = this.src;
                            link.download = `图${index + 1}`;
                            link.click();
                        });
                    });
                };
                img.src = e.target.result;
            };
            reader.readAsDataURL(file);
        }
    </script>

    <!-- 保存图片 -->

    <script>
        function chooseImage() {
            document.getElementById('upload').click();
        }



        saveBtn.onclick = function () {


            const zip = new JSZip();
            // const folder = zip.folder("九宫格图");
            if (imageParts.length === 0) {
                return alert('请先选择图片');
            }
            imageParts.forEach(part => {
                // folder.file(part.filename, part.data.split("base64,")[1], { base64: true });
                zip.file(part.filename, part.data.split("base64,")[1], { base64: true });
            });
            zip.generateAsync({ type: "blob" }).then(function (content) {
                saveAs(content, `九宫格图-${new Date().getTime()}.zip`);
            });
        };
    </script>
    <!-- 保存图片 -->

    <script>
        function isMobileDevice() {
            const userAgent = navigator.userAgent || navigator.vendor || window.opera;

            // 检查常见的移动设备标识符
            if (/android/i.test(userAgent)) {
                return true;
            }

            if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
                return true;
            }

            if (/windows phone/i.test(userAgent)) {
                return true;
            }

            if (/mobile/i.test(userAgent)) {
                return true;
            }

            return false;
        }



    </script>
    <script>
        let lastTouchX = null;
        let lastTouchY = null;
        let kuangkuang = document.querySelector('.kuangkuang');
        let previewBox = document.querySelector('#preview-box');
        let isStartMove = false;
        previewBox.addEventListener('touchmove', touchMove);
        previewBox.addEventListener('touchend', touchEnd);
        previewBox.addEventListener("mousemove", touchMove);
        previewBox.addEventListener('mouseup', touchEnd);
        previewBox.addEventListener('mousedown', () => {
            lastTouchX = event.pageX;
            lastTouchY = event.pageY;
            isStartMove = true;
        });


        let marginTop = 0;
        let marginLeft = 0;
        function touchMove(event) {
            if (!isMobileDevice() && !isStartMove) {
                return;
            }
            // console.log(event);
            //阻止事件冒泡
            event.preventDefault();

            if (lastTouchX === null) {
                if (isMobileDevice()) {

                    lastTouchX = event.changedTouches[0].pageX;
                    lastTouchY = event.changedTouches[0].pageY;
                } else {

                    lastTouchX = event.pageX;
                    lastTouchY = event.pageY;

                }


                return;
            }

            //根据位移量修改
            let x, y;
            if (isMobileDevice()) {
                x = event.changedTouches[0].pageX - lastTouchX;
                y = event.changedTouches[0].pageY - lastTouchY;
            } else {
                x = event.pageX - lastTouchX;
                y = event.pageY - lastTouchY;
            }

            let slace = 1;
            let width = Math.max(previewBox.clientWidth, previewBox.clientHeight);

            if (aspectRatio > 1) {
                marginLeft = marginLeft + x;
                if (Math.abs(marginLeft) > (width - 80) / 2) {
                    marginLeft = Math.abs(marginLeft) / marginLeft * (width - 80) / 2;
                }
                kuangkuang.style.marginLeft = marginLeft + 'px';
            } else {
                marginTop = marginTop + y;
                if (Math.abs(marginTop) > (width - 80) / 2) {
                    marginTop = Math.abs(marginTop) / marginTop * (width - 80) / 2;
                }
                kuangkuang.style.marginTop = marginTop + 'px';

            }
            if (isMobileDevice()) {
                lastTouchX = event.changedTouches[0].pageX;
                lastTouchY = event.changedTouches[0].pageY;
            } else {
                lastTouchX = event.pageX;
                lastTouchY = event.pageY;
            }





            //根据aspectRatio 计算移动的距离
            if (aspectRatio > 1) {
                if (Math.abs(marginLeft) === 0) return;
                leftCha = Math.abs(marginLeft) / marginLeft * cha * (Math.abs(marginLeft) / ((width - 80))) * -1;
            } else {
                if (Math.abs(marginTop) === 0) return;
                topCha = Math.abs(marginTop) / marginTop * cha * (Math.abs(marginTop) / ((width - 80))) * -1;
            }

        }
        function touchEnd(event) {
            lastTouchX = null;
            lastTouchY = null;
            isStartMove = false;
            if (isMobileDevice()) {
                drawImageHandler(true);
            } else {
                drawImageHandler(true);
            }
        }
        function editWidth() {
            var width = prompt("请输入图片间隙", storeWidht);
            width = parseInt(width || storeWidht);
            if (!(width >= 0)) {
                width = 4;
            }
            storeWidht = width;
            let imgsList = document.querySelector('.imgs-list');
            imgsList.style.width = `${300 + 2 * width}px`;
            imgsList.style.height = `${300 + 2 * width}px`;
            imgsList.style.setProperty('--store-width', `${width}px`);
            drawImageHandler(true);

        }
        // editWidth();
    </script>
</body>

</html>